package com.maozzi.service.user.domain.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maozzi.api.user.constant.UserConst;
import com.maozzi.api.user.enums.UserTypeEnum;
import com.maozzi.common.enums.BizCodeEnum;
import com.maozzi.common.exception.BizException;
import com.maozzi.common.util.ParamCheckUtil;
import com.maozzi.service.user.domain.UserDomainService;
import com.maozzi.service.user.repository.mapper.UserMapper;
import com.maozzi.service.user.repository.model.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * user domain service
 *
 * @author maozi
 */
@Service
public class UserDomainServiceImpl extends ServiceImpl<UserMapper, User> implements UserDomainService {

    @Override
    public void signup(User user) {
        ParamCheckUtil.notNull(user, "参数错误");

        // 检查用户名是否重复
        this.checkName(user.getName());

        user.setId(null)
                .setType(UserTypeEnum.NORMAL.getCode())
                .setCreateDate(null)
                .setCreateBy(user.getName())
                .setModifiedDate(null)
                .setModifiedBy(null)
                .setDeleted(false);

        if (!StringUtils.hasText(user.getAvatar())) {
            // 设置默认头像
            user.setAvatar(UserConst.default_avatar);
        }

        this.save(user);
    }

    /**
     * 检查用户名是否重复
     *
     * @param name    用户名
     * @param userIds 排除项
     */
    private void checkName(String name, Long... userIds) {
        LambdaQueryWrapper<User> query = Wrappers.lambdaQuery(User.class)
                .eq(User::getName, name)
                .eq(User::getDeleted, false);
        if (Objects.nonNull(userIds) && userIds.length > 0) {
            query.notIn(User::getId, (Object[]) userIds);
        }

        long count = this.count(query);
        if (count > 0) {
            throw new BizException(BizCodeEnum.WRONG_PARAMETERS, "用户名重复");
        }
    }

    @Override
    public User getUser(Long userId) {
        User user = this.getById(userId);
        if (Objects.isNull(user)) {
            return null;
        }

        user.setPassword(null);
        return user;
    }

    @Override
    public User getUser(String name, String password) {
        LambdaQueryWrapper<User> query = Wrappers.lambdaQuery(User.class)
                .eq(User::getName, name)
                .eq(User::getPassword, password)
                .eq(User::getDeleted, false)
                .last("limit 1");

        return this.getOne(query);
    }

    @Override
    public List<User> userListBatch(List<Long> userIds) {
        ParamCheckUtil.notNull(userIds, "参数错误");

        ArrayList<User> list = new ArrayList<>();
        if (userIds.isEmpty()) {
            return list;
        }

        // 分页、查询条件
        Page<User> page = Page.of(1L, 100L);
        page.setPages(0L);
        LambdaQueryWrapper<User> query = Wrappers.lambdaQuery(User.class)
                .eq(User::getDeleted, false)
                .orderByDesc(User::getId);

        do {
            page.setPages(page.getPages() + 1);
            page = this.page(page, query);
            if (Objects.nonNull(page) && Objects.nonNull(page.getRecords()) && !page.getRecords().isEmpty()) {
                list.addAll(page.getRecords());
            }
        } while (page.hasNext());

        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateUserTypeById(List<Long> userIds, UserTypeEnum userType) {
        ParamCheckUtil.notNull(userIds, "参数错误");
        ParamCheckUtil.notNull(userType, "参数错误");

        int step = 100;
        Long[] array = userIds.toArray(new Long[]{});
        for (int i = 0; i < array.length; i += step) {
            int to = i + step;
            if (to >= array.length) {
                to = array.length - 1;
            }
            Long[] arr = Arrays.copyOfRange(array, i, to);
            LambdaUpdateWrapper<User> query = Wrappers.lambdaUpdate(User.class)
                    .set(User::getType, userType.getCode())
                    .in(User::getId, (Object[]) arr);
            this.update(query);
        }

        return true;
    }


}
